package com.iplant.ams.serviceImpl.dao.ams;

import com.iplant.ams.service.po.ams.AMSPurchaseRequestItem;
import com.iplant.base.po.OutResult;
import com.iplant.base.po.Pagination;
import com.iplant.base.po.ServiceResult;
import com.iplant.base.po.enums.ExceptionTypes;
import com.iplant.base.utils.general.CalendarTool;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.base.utils.sql.BaseDAO;
import com.iplant.basic.service.po.bms.BMSEmployee;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class AMSPurchaseRequestItemDAO extends BaseDAO {

    private static Logger logger = LoggerFactory.getLogger(AMSPurchaseRequestItemDAO.class);

    private static AMSPurchaseRequestItemDAO Instance = null;

    public static AMSPurchaseRequestItemDAO getInstance() {
        if (Instance == null) {
            Instance = new AMSPurchaseRequestItemDAO();
        }
        return Instance;
    }

    /**
     * 新增或更新
     *
     * @param wLoginUser
     * @param wItem
     * @param wErrorCode
     * @return
     */
    public int Update(BMSEmployee wLoginUser, AMSPurchaseRequestItem wItem, OutResult<Integer> wErrorCode) {
        int wResult = 0;

        try {
            if (wItem == null) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return wResult;
            }

            wItem.setUserInfo(wLoginUser);
            wResult = this.UpdatePo(wLoginUser, wItem, wErrorCode);
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error(ex.toString());
        }

        return wResult;
    }

    /**
     * 创建采购单时，更新申请项的已采购数目为当前数目+本次采购数目
     *
     * @param wLoginUser
     * @param wID
     * @param wPurchaseQuantity
     * @param wErrorCode
     * @return
     */
    public int UpdatePurchaseQuantity(BMSEmployee wLoginUser, int wID, int wPurchaseQuantity, OutResult<Integer> wErrorCode) {
        int wResult = 0;

        try {
            if (wID <= 0) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return wResult;
            }

            // 查询出申请数量和已采购数量，用于校验是否还能进行采购，防止前端提供的已购数量不准确
            String wSQL = StringUtils.Format(
                    "SELECT t.* FROM {0}.ams_purchase_request_item t WHERE t.ID = :wID", super.getDBName());
            Map<String, Object> wParamMap = new HashMap<>();
            wParamMap.put("wID", wID);

            wSQL = this.DMLChange(wSQL);

            Pagination wPagination = Pagination.getMaxSize();
            List<AMSPurchaseRequestItem> wItemListTemp = this.QueryForList(wSQL, wParamMap, wPagination, AMSPurchaseRequestItem.class);
            if (wItemListTemp == null || wItemListTemp.isEmpty()) {
                wErrorCode.set(ExceptionTypes.DataInvalid.getValue());
                return wResult;
            }
            AMSPurchaseRequestItem wItemTemp = wItemListTemp.get(0);

            // 校验数量，已购数量+本次采购数量是否大于申请数量
            if (wItemTemp.getPurchaseQuantity() + wPurchaseQuantity > wItemTemp.getRequestQuantity()) {
                wErrorCode.set(ExceptionTypes.DataInvalid.getValue());
                return wResult;
            }

            wSQL = StringUtils.Format(
                    "UPDATE {0}.ams_purchase_request_item " +
                            " SET PurchaseQuantity = PurchaseQuantity + :wPurchaseQuantity, " +
                            " EditorID = :wEditorID, EditTime = :wEditTime " +
                            " WHERE ID = :wID ", super.getDBName());

            wParamMap = new HashMap<>();
            wParamMap.put("wID", wID);
            wParamMap.put("wEditorID", wLoginUser.getID());
            wParamMap.put("wEditTime", Calendar.getInstance());
            wParamMap.put("wPurchaseQuantity", wPurchaseQuantity);

            wSQL = this.DMLChange(wSQL);

            super.Update(wSQL, wParamMap);
            wResult = wID;
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error(ex.toString());
        }

        return wResult;
    }

    /**
     * 单条删除
     *
     * @param wLoginUser
     * @param wItem
     * @param wErrorCode
     * @return
     */
    public ServiceResult<Integer> Delete(BMSEmployee wLoginUser, AMSPurchaseRequestItem wItem, OutResult<Integer> wErrorCode) {
        ServiceResult<Integer> wResult = new ServiceResult<Integer>(0);

        try {
            if (wItem == null || wItem.getID() <= 0) {
                wErrorCode.set(ExceptionTypes.DataInvalid.getValue());
                return wResult;
            }

            // 判断是否满足删除的条件
            // ...

            this.DeletePO(wLoginUser, wItem, wErrorCode);
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error(ex.toString());
        }

        return wResult;
    }

    /**
     * 批量删除
     *
     * @param wLoginUser
     * @param wIDList
     * @param wErrorCode
     */
    public ServiceResult<Integer> DeleteList(BMSEmployee wLoginUser, List<Integer> wIDList, OutResult<Integer> wErrorCode) {
        ServiceResult<Integer> wResult = new ServiceResult<Integer>(0);

        try {
            if (wIDList == null || wIDList.isEmpty()) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return wResult;
            }
            wIDList.removeIf(p -> p <= 0);
            if (wIDList.isEmpty()) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return wResult;
            }

            // 批量删除SQL语句
            String wSQL = StringUtils.Format(
                    "DELETE FROM {0}.ams_purchase_request_item WHERE ID in ({1})",
                    super.getDBName(), StringUtils.Join(",", wIDList));
            Map<String, Object> wParamMap = new HashMap<>();
            wSQL = this.DMLChange(wSQL);
            wResult.Result = super.Update(wSQL, wParamMap);
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error(ex.toString());
        }

        return wResult;
    }

    /**
     * 用RequestID查清单
     *
     * @param wLoginUser
     * @param wRequestID
     * @param wErrorCode
     * @return
     */
    public List<AMSPurchaseRequestItem> SelectListByRequestID(BMSEmployee wLoginUser, int wRequestID, OutResult<Integer> wErrorCode) {
        List<AMSPurchaseRequestItem> wResultList = new ArrayList<>();

        try {
            if (wRequestID <= 0) {
                return wResultList;
            }

            wResultList = this.SelectList(wLoginUser, null, "", "", -1, -1,
                    null, wRequestID, CalendarTool.getBasicDate(), CalendarTool.getBasicDate(), Pagination.getMaxSize(), wErrorCode);
        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error(ex.toString());
        }

        return wResultList;
    }

    /**
     * 条件查询
     *
     * @param wLoginUser
     * @param wIDs
     * @param wName
     * @param wCode
     * @param wCreatorID
     * @param wActive
     * @param wStateIDList
     * @param wRequestID
     * @param wStartTime
     * @param wEndTime
     * @param wPagination
     * @param wErrorCode
     * @return
     */
    public List<AMSPurchaseRequestItem> SelectList(BMSEmployee wLoginUser, List<Integer> wIDs, String wName, String wCode,
            int wCreatorID, int wActive, List<Integer> wStateIDList, int wRequestID,
            Calendar wStartTime, Calendar wEndTime, Pagination wPagination, OutResult<Integer> wErrorCode) {
        List<AMSPurchaseRequestItem> wResultList = new ArrayList<>();

        try {
            // ID List
            if (wIDs == null) {
                wIDs = new ArrayList<>();
            }
            wIDs.removeIf(p -> p <= 0);

            // StateID List
            if (wStateIDList == null) {
                wStateIDList = new ArrayList<>();
            }

            // 时间的处理
            Calendar wBaseTime = CalendarTool.getBasicDate();
            wBaseTime.set(2000, 1, 1);
            if (wStartTime == null || wStartTime.compareTo(wBaseTime) < 0) {
                wStartTime = wBaseTime;
            }
            if (wEndTime == null || wEndTime.compareTo(wBaseTime) < 0) {
                wEndTime = wBaseTime;
            }
            if (wStartTime.compareTo(wEndTime) > 0) {
                return wResultList;
            }

            String wSQL = StringUtils.Format(
                    "SELECT t1.*, t2.Name as AssetName, t2.AssetModel as AssetModel, t2.AssetUnit as AssetUnit " +
                            "FROM {0}.ams_purchase_request_item t1 " +
                            "LEFT JOIN {0}.ams_asset_standard_model t2 ON t1.AssetStandardModelID = t2.ID " +
                            "WHERE t1.ID > 0 " +
                            " AND (:ID = '''' or t1.ID IN (''{1}'')) " +
                            " AND (:Name = '''' OR t1.Name like :Name) " +
                            " AND (:Code = '''' OR t1.Code like :Code) " +
                            " AND (:CreatorID <= 0 OR t1.CreatorID = :CreatorID ) " +
                            " AND (:Active < 0 OR t1.Active = :Active) " +
                            " AND (:Status = '''' OR t1.CurrentStatus IN (''{2}'')) " +
                            " AND (:RequestID <= 0 OR t1.RequestID = :RequestID ) " +
                            " AND (:StartTime <= str_to_date(''2010-01-01'', ''%Y-%m-%d'') OR :StartTime <= t1.CreateTime) " +
                            " AND (:EndTime <= str_to_date(''2010-01-01'', ''%Y-%m-%d'') OR :EndTime >= t1.CreateTime) ",
                    super.getDBName(), StringUtils.Join("','", wIDs), StringUtils.Join("','", wStateIDList));

            Map<String, Object> wParamMap = new HashMap<>();
            wParamMap.put("ID", StringUtils.Join(",", wIDs));
            wParamMap.put("Name", StringUtils.isEmpty(wName) ? "" : ("%" + wName + "%"));
            wParamMap.put("Code", StringUtils.isEmpty(wCode) ? "" : ("%" + wCode + "%"));
            wParamMap.put("CreatorID", wCreatorID);
            wParamMap.put("Active", wActive);
            wParamMap.put("Status", StringUtils.Join(",", wStateIDList));
            wParamMap.put("RequestID", wRequestID);
            wParamMap.put("StartTime", wStartTime);
            wParamMap.put("EndTime", wEndTime);

            wSQL = this.DMLChange(wSQL);

            wResultList = this.QueryForList(wSQL, wParamMap, wPagination, AMSPurchaseRequestItem.class);
        } catch (Exception ex) {
            wErrorCode.set(Integer.valueOf(ExceptionTypes.DBSQL.getValue()));
            logger.error(ex.toString());
        }

        return wResultList;
    }


    /**
     * 高级注解式条件查询
     *
     * @param wLoginUser
     * @param wParams
     * @param wPagination
     * @param wErrorCode
     * @return
     */
    public List<AMSPurchaseRequestItem> SelectList(BMSEmployee wLoginUser,
            Map<String, Object> wParams, Pagination wPagination, OutResult<Integer> wErrorCode) {

        return this.SelectPOList(wLoginUser, wParams, AMSPurchaseRequestItem.class, wPagination, wErrorCode);
    }
}
